package top.saplf.sileny.player.home

import android.content.Intent
import android.os.Bundle
import android.os.Environment
import android.support.v4.app.ActivityOptionsCompat
import android.support.v4.app.SharedElementCallback
import android.support.v7.app.AlertDialog
import android.support.v7.widget.LinearLayoutManager
import android.util.Base64
import android.view.View
import android.view.ViewTreeObserver
import com.github.ajalt.timberkt.Timber
import com.jakewharton.rxbinding2.support.v4.widget.refreshes
import com.nbsp.materialfilepicker.MaterialFilePicker
import com.nbsp.materialfilepicker.ui.FilePickerActivity
import io.realm.Realm
import io.realm.Sort
import kotlinx.android.synthetic.main.fragment_local_music_index.*
import me.eugeniomarletti.extras.bundle.BundleExtra
import me.eugeniomarletti.extras.bundle.base.String
import org.jaudiotagger.audio.mp3.MP3File
import org.jaudiotagger.tag.id3.AbstractID3v2Frame
import org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC
import top.saplf.sileny.R
import top.saplf.sileny.base.ui.SilenyFragment
import top.saplf.sileny.editor.home.Note
import top.saplf.sileny.ext.cacheSharedPref
import top.saplf.sileny.ext.musicMetaData
import top.saplf.sileny.ext.write
import java.io.File
import java.util.*
import java.util.regex.Pattern

/**
 * @author saplf
 */
class LocalMusicIndexFragment : SilenyFragment() {

    companion object {
        private const val MUSIC_PICKER_REQUEST_CODE = 0
        private const val MUSIC_DETAIL_REQUEST_CODE = 1
        private const val LAST_MUSIC_CHOOSE_PATH = "last music choose path"

        private var Bundle.currentMusicId: String by BundleExtra.String("")

        fun getInstance(): LocalMusicIndexFragment = LocalMusicIndexFragment()
    }

    private val mRealm: Realm by lazy { Realm.getDefaultInstance() }
    private val mAdapter: LocalMusicIndexAdapter by lazy {
        LocalMusicIndexAdapter().apply {
            bindToRecyclerView(musicList)
            addData(getDataFromRealm())
            itemAction = { (id), sharedView ->
                mCurrentMusicId = id
                val options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, sharedView, id)
                activity.startActivityForResult(Intent(context, LocalMusicActivity::class.java).apply {
                    with(LocalMusicActivity) {
                        musicId = id
                    }
                }, MUSIC_DETAIL_REQUEST_CODE, options.toBundle())
            }
            longItemAction = { (id) ->
                AlertDialog.Builder(context)
                        .setMessage("是否从列表移除？")
                        .setPositiveButton("确定") { dialog, _ ->
                            dialog.dismiss()
                            mRealm.beginTransaction()
                            mAdapter.data.find { it.id == id }?.deleteFromRealm()
                            mRealm.commitTransaction()
                            mAdapter.setNewData(mRealm.where(Music::class.java).findAll().sort(Music::name.name))
                        }
                        .setNegativeButton("取消") { dialog, _ -> dialog.dismiss() }
                        .create()
                        .show()
            }
        }
    }
    private val mSharedElementCallback: SharedElementCallback by lazy {
        object : SharedElementCallback() {
            override fun onMapSharedElements(names: MutableList<String>, sharedElements: MutableMap<String, View>) {
                names.clear()
                names.add(mCurrentMusicId)
                sharedElements.clear()
                sharedElements.put(mCurrentMusicId, mAdapter.getSharedElement(mCurrentMusicId))
            }
        }
    }
    private var mCurrentMusicId: String = ""

    override fun onLayoutRes(): Int = R.layout.fragment_local_music_index

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        with(musicList) {
            layoutManager = LinearLayoutManager(context)
            adapter = mAdapter
        }

        swipeLayout.refreshes()
                .subscribe {
                    swipeLayout.isRefreshing = false
                    mAdapter.setNewData(getDataFromRealm())
                }

        if (savedInstanceState != null) {
            mCurrentMusicId = savedInstanceState.currentMusicId
        }

        activity.setExitSharedElementCallback(mSharedElementCallback)
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.currentMusicId = mCurrentMusicId
    }

    override fun onDestroy() {
        super.onDestroy()
        mRealm.close()
    }

    private fun getDataFromRealm() = mRealm.where(Music::class.java).findAll().sort(Music::name.name)

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (data == null) return
        if (requestCode == MUSIC_PICKER_REQUEST_CODE &&
                resultCode == FilePickerActivity.RESULT_OK) {
            val path = data.getStringExtra(FilePickerActivity.RESULT_FILE_PATH)
            val lastSeparator = path.lastIndexOf(File.separatorChar)
            cacheSharedPref.write {
                putString(LAST_MUSIC_CHOOSE_PATH, path.substring(0, lastSeparator))
            }
            val v2Tag = MP3File(path).iD3v2Tag
            with(v2Tag.frameMap) {
                val cover = this["APIC"] as AbstractID3v2Frame
                val body = cover.body as FrameBodyAPIC
                val music = Music(
                        UUID.randomUUID().toString(),
                        this["TIT2"].musicMetaData(),
                        path,
                        true,
                        this["TPE1"].musicMetaData(),
                        this["TALB"].musicMetaData(),
                        Base64.encodeToString(body.imageData, Base64.DEFAULT)
                )
                mRealm.beginTransaction()
                mRealm.insert(music)
                mRealm.commitTransaction()
                mAdapter.setNewData(getDataFromRealm())
            }
        }
    }

    fun onActivityReenter(resultCode: Int, data: Intent?) {
        if (resultCode == LocalMusicActivity.RESULT_CODE && data != null) {
            with(LocalMusicActivity) {
                mCurrentMusicId = data.musicId.apply {
                    if (mCurrentMusicId != this) {
                        musicList.scrollToPosition(mAdapter.data.indexOfFirst { it.id == this })
                    }
                }
                activity.postponeEnterTransition()
                musicList.viewTreeObserver.addOnPreDrawListener(onPreDrawListener)
            }
        }
    }

    private val onPreDrawListener: ViewTreeObserver.OnPreDrawListener by lazy {
        object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                musicList.viewTreeObserver.removeOnPreDrawListener(this)
                musicList.requestLayout()
                activity.startPostponedEnterTransition()
                return true
            }
        }
    }

    fun actionClick() {
        MaterialFilePicker()
                .withActivity(activity)
                .withRequestCode(MUSIC_PICKER_REQUEST_CODE)
                .withFilter(Pattern.compile(".*\\.mp3$"))
                .withPath(cacheSharedPref.getString(LAST_MUSIC_CHOOSE_PATH, Environment.getExternalStorageDirectory().absolutePath))
                .withHiddenFiles(false)
                .start()
    }
}
